﻿/*
 * rtvalue.hpp
 *
 *  Created on: 2017年3月27日
 *      Author: work
 */

#ifndef _DM_SCADA_RTVALUE_HPP_
#define _DM_SCADA_RTVALUE_HPP_

#include <dm/timestamp.hpp>
#include <dm/scada/datasource.hpp>
#include <dm/os/spinlock.hpp>
#include <dm/os/scopelock.hpp>

namespace dm{
namespace scada{

template<typename T>
class TCRtValue{
public:
	TCRtValue( const T& v=T(),const EDataSource& ds=BySys,const dm::CTimeStamp& ts= dm::CTimeStamp::cur()):m_ts(ts),m_v(v),m_ds(ds),m_lock(){
	}

	inline dm::CTimeStamp getTimeStamp()const{
		return m_ts;
	}

	inline T getValue()const{
		return m_v;
	}

	inline EDataSource getDataSource()const{
		return m_ds;
	}

	inline void setTimeStamp( const dm::CTimeStamp& ts ){
		dm::os::CScopeLock lock(m_lock);
		m_ts.copy(ts);
	}

	inline void setValue( const T& v ){
		dm::os::CScopeLock lock(m_lock);
		m_v = v;
	}

	inline void setDataSource( const EDataSource& ds ){
		dm::os::CScopeLock lock(m_lock);
		m_ds = ds;
	}

	inline bool update( const T& v,const EDataSource& ds,const dm::CTimeStamp& ts=dm::CTimeStamp::cur() ){
		dm::os::CScopeLock lock(m_lock);
		m_ts.copy(ts);
		m_ds = ds;
		return m_v.update(v);
	}

	inline void load( T& v,EDataSource& ds,dm::CTimeStamp& ts ){
		dm::os::CScopeLock lock(m_lock);
		v = m_v;
		ds = m_ds;
		ts = m_ts;
	}

	inline bool checkAndLoad( T& v,EDataSource& ds,dm::CTimeStamp& ts ){
		dm::os::CScopeLock lock(m_lock);
		if( v==m_v )
			return false;
		else{
			v = m_v;
			ds = m_ds;
			ts = m_ts;
			return true;
		}
	}

private:
	volatile dm::CTimeStamp m_ts;
	volatile T m_v;
	volatile EDataSource m_ds;

	dm::os::CSpinlock m_lock;
};

}
}

#endif /* INCLUDE_DM_SCADA_RTVALUE_HPP_ */
